﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net.Sockets;

public class MessagePacketRouting 
{
    public MessagePacketRouting()
    {

    }

    private object m_Token;
    
    public MessagePacketRouting(object token)
    {
        m_Token = token;
    }

    public Dictionary<string, Func<NetEvent>> netEventDict = new Dictionary<string, Func< NetEvent>>();

    List<MessagePacket> m_ReceivedMessage = new List<MessagePacket>();
    public void RegisterEvent(string key,Func<NetEvent> netEvent )
    {
        if (netEventDict.ContainsKey(key))
        {
            Debug.LogError("RegisterEvent ContainsKey: " + key);
            return;
        }
        netEventDict[key] = netEvent;
    }

    AtomLock m_AtomLock = new AtomLock();
    public void OnReceivedMessage(MessagePacket messagePacketReceive)
    {
        m_AtomLock.DoAction(() =>
        {
            //GameDebug.Log($"Routing OnReceivedMessage");
            m_ReceivedMessage.Add(messagePacketReceive);
        });
    }
    public bool ProcessMessage(MessagePacket messagePacketReceive)
    {
        string key = messagePacketReceive.key;
        Debug.Log("dispacher  event:" + key + "  seq:" + messagePacketReceive.seq+ "  type:" + messagePacketReceive.type);
        if (messagePacketReceive.type == MessagePacketType.Event)
        {
            if (netEventDict.ContainsKey(key))
            {
                //Debug.Log("dispacher  event:" + key + "  seq:" + messageReceive.seq);
                NetEvent netEvent = netEventDict[key]();
                
                bool readSuc = netEvent.Init(m_Token,messagePacketReceive);
                if (!readSuc)
                    return false;
                    //  netEvent.Read();
               
                UnityThread.PostAction(() =>
                {
                    try
                    {
                        netEvent.Excuate();
                    }
                    catch(Exception e)
                    {
                        GameDebug.LogError(e);
                    }
                });
            }
            else
            {
                Debug.LogError("Event 找不到处理相应处理 key:" + key);
            }
        }
        else if (messagePacketReceive.type == MessagePacketType.Response)
        {
            RequestBase requestBase = m_RequestCollection.GetNetRequest(messagePacketReceive.seq);

            if (requestBase != null)
            {
                ResponseBase response = new ResponseBase();// //requestBase.GetResponseHandler();

                if (response == null)
                {
                    Debug.LogError("response == null request type:" + key);
                }
                else
                {
                    bool readSuc = response.Init(messagePacketReceive, requestBase);
                    if(!readSuc)
                    {
                        GameDebug.LogError($"read failed :{key}  data:{BitConverter.ToString(messagePacketReceive.data)}");
                        return false;
                    }

                    UnityThread.PostAction(() =>
                    {
                        response.Excuate();
                    });
                }
                
                lock(m_ToRemove)
                {
                   m_ToRemove.Add(requestBase.MessagePacket.seq);
                }
            }
            else
            {
                string dict = "";
                foreach (var kv in m_RequestCollection.requestDict)
                    dict += "["+kv.Key + ":" + kv.Value+"],";

                Debug.LogError($"response 找不到处理相应 key:{key}  seq:{messagePacketReceive.seq}  dict:{dict}" );
            }
        }
        return true;
    }

    RequestCollection m_RequestCollection = new RequestCollection();
    public RequestCollection requestCollection
    {
        get { return m_RequestCollection; }
    }

    public void AddRequest(RequestBase requestBase)
    {
        if (requestBase.MessagePacket == null)
        {
            GameDebug.LogError($"request.message == null ");
        }
        else
        {  
            //GameDebug.Log($"发送请求：{request.message.key}  seq:{request.message.seq}");
            if (requestBase.needResponse)
            {
                //GameDebug.Log($"添加请求：{request.message.key} seq:{request.message.seq}");

                //lock(m_ToAdd)
                //{
                //    m_ToAdd.Add(requestBase);
                //}
                lock (m_RequestCollection)
                {
                    m_RequestCollection.AddRequest(requestBase.MessagePacket.seq, requestBase);
                }
            }
        }
    }

    List<int> m_ToRemove = new List<int>();
    List<RequestBase> m_ToAdd = new List<RequestBase>();

    public void Update()
    {   
        //lock(m_ToAdd)
        //{
        //    if (m_ToAdd.Count > 0)
        //    {
        //        // lock (batonToAdd)
        //        m_ToAdd.ForEach(request => { m_RequestCollection.AddRequest(request.MessagePacket.seq, request); });

        //        m_ToAdd.Clear();
        //    }
        //}


        //lock (RequestCollection.dictLock)
        {
            if (this.m_RequestCollection.requestDict.Count > 0)
            {
                double curTime = CommonFunctions.GetTimeStampSeconds();

                foreach (RequestBase request in this.m_RequestCollection.requestDict.Values)
                {
                    if (curTime - request.sendTime > request.timeOutSeconds)
                    {
                        //超时了
                        GameDebug.LogShowy($"{request.MessagePacket.key}  seq:{request.MessagePacket.seq}  请求超时");
                        request.onTimeOut?.Invoke(request);
                        
                        lock (m_ToRemove)
                        {
                            m_ToRemove.Add(request.MessagePacket.seq);
                        }
                     }
                }
            }

        }
        
        lock (m_ToRemove)
        { 
            if (m_ToRemove.Count > 0)
            {
                m_ToRemove.ForEach(e => this.m_RequestCollection.RemoveRequest(e));
                m_ToRemove.Clear();
            }
        }
        
        m_AtomLock.DoAction(() =>
        {
            if (m_ReceivedMessage.Count > 0)
            {
                //GameDebug.Log($"m_ReceivedMessage count:{m_ReceivedMessage.Count}");
                var newMessage = new List<MessagePacket>(m_ReceivedMessage);

                newMessage.ForEach(e => { this.ProcessMessage(e); });
                newMessage = null;

                m_ReceivedMessage.Clear();
            }
        });
    }

    public void OnDisconnect()
    {
        GameDebug.Log("OnDisconnect!");//throw new NotImplementedException();
    }

    public void OnReLogin()
    {
        GameDebug.Log("OnReLogin");
    }

  
}
